package com.hzncc.flowable_diboot.payment.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.diboot.core.binding.Binder;
import com.diboot.core.holder.ThreadLocalHolder;
import com.diboot.core.util.BeanUtils;
import com.diboot.core.util.S;
import com.diboot.core.vo.LabelValue;
import com.diboot.iam.entity.IamUser;
import com.diboot.iam.service.IamUserService;
import com.diboot.iam.util.IamSecurityUtils;
import com.diboot.tenant.service.IamTenantService;
import com.hzncc.flowable_diboot.entity.SalesGroupContent;
import com.hzncc.flowable_diboot.exception.BusinessException;
import com.hzncc.flowable_diboot.payment.entity.*;
import com.hzncc.flowable_diboot.payment.service.*;
import com.hzncc.flowable_diboot.payment.vo.*;
import com.hzncc.flowable_diboot.service.SalesGroupContentService;
import com.hzncc.flowable_diboot.service.SapCustomerService;
import com.hzncc.flowable_diboot.util.SapUtil;
import com.sap.conn.jco.JCoException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.diboot.core.service.impl.BaseServiceImpl;

import com.hzncc.flowable_diboot.mapper.PaymentCertMapper;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.Year;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 回款凭证 相关Service实现类
 *
 * @author MyName
 * @version 1.0
 * @date 2024-10-25
 * Copyright © MyCorp
 */
@Slf4j
@Service
public class PaymentCertServiceImpl extends BaseServiceImpl<PaymentCertMapper, PaymentCert> implements PaymentCertService {

    private static final String accountingPeriod = "10";

    private static final String certType = "DZ";

    @Resource
    private PaymentRegisterService paymentRegisterService;

    @Resource
    private PaymentContractService paymentContractService;

    @Resource
    private SapUtil sapUtil;

    @Autowired
    private IamTenantService iamTenantService;

    @Autowired
    private SalesGroupContentService salesGroupContentService;

    @Autowired
    private PaymentCertItemService paymentCertItemService;

    @Autowired
    private SapPaymentContractService sapPaymentContractService;

    @Override
    public PaymentCertDetailVO genPaymentCert(String paymentRegisterId) {
        PaymentRegisterDetailVO paymentRegister = paymentRegisterService.getViewObject(paymentRegisterId, PaymentRegisterDetailVO.class);
        String year = String.valueOf(Year.now().getValue());//会计年度
        LocalDateTime now = LocalDateTime.now();
        PaymentCertDetailVO paymentCertDetailVO = new PaymentCertDetailVO();
        paymentCertDetailVO.setPaymentRegisterId(paymentRegisterId).setYear(year).setCertDate(now).setPostDate(now)
                .setAccountingPeriod(now.format(DateTimeFormatter.ofPattern("MM"))).setCertType(certType)
                .setCertTitle(paymentRegister.getCustomerName() + "回款").setCurrencyCode("CNY");

        paymentCertDetailVO.setPaymentRegister(paymentRegister);
        LambdaQueryWrapper<PaymentContract> paymentContractQuery = new LambdaQueryWrapper<>();
        paymentContractQuery.eq(PaymentContract::getPaymentRegisterId, paymentRegisterId).eq(PaymentContract::isDeleted, 0);
        // 获取所有租户合同收款
        ThreadLocalHolder.setIgnoreInterceptor();
        List<PaymentContract> paymentContractList = paymentContractService.getEntityList(paymentContractQuery);
        if (paymentContractList == null || paymentContractList.isEmpty()) {
            throw new BusinessException("未找到合同收款信息");
        }
        List<PaymentContractListVO> paymentContractListVOS = Binder.convertAndBindRelations(paymentContractList, PaymentContractListVO.class);
        LambdaQueryWrapper<SapPaymentContract> sapPaymentContractQuery = new LambdaQueryWrapper<>();
        sapPaymentContractQuery.in(SapPaymentContract::getPaymentContractId, paymentContractList.stream().map(PaymentContract::getId).toList());
        // 获取SAP合同收款
        ThreadLocalHolder.setIgnoreInterceptor();
        List<SapPaymentContract> sapPaymentContracts = sapPaymentContractService.getEntityList(sapPaymentContractQuery);
        List<SapPaymentContractDetailVO> sapPaymentContractDetailVOS = Binder.convertAndBindRelations(sapPaymentContracts, SapPaymentContractDetailVO.class);
        Map<String, List<SapPaymentContractDetailVO>> sapPaymentContractMap = sapPaymentContractDetailVOS.stream().collect(Collectors.groupingBy(SapPaymentContract::getPaymentContractId));
        // 列表转换
        List<PaymentContractDetailVO> paymentContractDetailVOS = new ArrayList<>();
        for (PaymentContractListVO paymentContractListVO : paymentContractListVOS) {
            PaymentContractDetailVO paymentContractDetailVO = new PaymentContractDetailVO();
            BeanUtils.copyProperties(paymentContractListVO, paymentContractDetailVO);
            paymentContractDetailVO.setSapPaymentContractList(sapPaymentContractMap.getOrDefault(paymentContractListVO.getId(),new ArrayList<>()));
            paymentContractDetailVOS.add(paymentContractDetailVO);
        }
        paymentCertDetailVO.setCompanyContractType(paymentContractList.stream().map(PaymentContract::getCompanyContractsType).filter(Objects::nonNull).findFirst().orElse(""));
        // 成本中心
        paymentCertDetailVO.setCostCenter(paymentContractListVOS.stream().map(e -> e.getCostCenterLabel().getLabel()).filter(Objects::nonNull).findFirst().orElse(""));
        // 销售员
        paymentCertDetailVO.setSalesperson(paymentContractListVOS.stream().map(PaymentContractListVO::getSalerLabel).filter(Objects::nonNull).findFirst().orElse(""));
        // 客户名称
        paymentCertDetailVO.setCustomerName(paymentRegister.getSapCustomerName());
        // 销售部门
        paymentCertDetailVO.setSalesDept(paymentContractListVOS.stream().map(PaymentContractListVO::getSalesAreaLabel).filter(Objects::nonNull).map(LabelValue::getLabel).findFirst().orElse(""));
        String dis = "";
        String contractCode = "";
        // 费用报销单 第一条来源回款登记 = 总账 其余合同收款 = 明细
        ArrayList<PaymentCertItemListVO> paymentCertItems = new ArrayList<>();
        // 回款登记 回款类型判断
        PaymentCertItemListVO paymentCertItem = new PaymentCertItemListVO();
        if (S.equals(paymentRegister.getType(), "10") || S.equals(paymentRegister.getType(), "20")) {
            paymentCertItem.setAccountCode("40");
            paymentCertItem.setAccountTitle(S.equals(paymentRegister.getType(), "10") ? "1001000001" : paymentRegister.getPaymentItem());
//            paymentCertItem.setCostCenter(paymentRegister.getCostCenter());
        } else {
            paymentCertItem.setAccountCode("09");
//            paymentCertItem.setAccountTitle(S.equals(paymentRegister.getType(), "10") ? "1001000001":paymentRegister.getPaymentItem());
//            paymentCertItem.setCostCenter(paymentRegister.getCostCenter());
            paymentCertItem.setCustomerCode(paymentRegister.getCustomerCode());
            paymentCertItem.setLedgerFlag(S.equals(paymentRegister.getType(), "30") ? "1" : S.equals(paymentRegister.getType(), "40") ? "2" : "");
            paymentCertItem.setAssignmentCode(paymentRegister.getBillNum());
        }
        paymentCertItem.setBaseDate(paymentRegister.getPaymentTime());
        paymentCertItem.setCurrencyAmount(paymentRegister.getPaymentAmount());
        paymentCertItem.setReasonCode("A01");
        paymentCertItem.setProjectText(paymentContractListVOS.stream().map(PaymentContractListVO::getSapCustomerName).collect(Collectors.joining(",")));
        paymentCertItems.add(paymentCertItem);
        for (PaymentContractDetailVO paymentContract : paymentContractDetailVOS) {
            List<SapPaymentContractDetailVO> sapPaymentContractList = new ArrayList<>(paymentContract.getSapPaymentContractList().stream().filter(item -> item.getCurrentCollectionAmount().compareTo(BigDecimal.ZERO) > 0).toList());
            LambdaQueryChainWrapper<SalesGroupContent> query = salesGroupContentService.lambdaQuery().select(SalesGroupContent::getDis)
                    .eq(SalesGroupContent::getSapCustomerId, paymentContract.getSapCustomer()).eq(SalesGroupContent::getIsFreeze, "0");
            ThreadLocalHolder.setIgnoreInterceptor();
            List<SalesGroupContent> entityList = salesGroupContentService.getEntityList(query);
            if (sapPaymentContractList.isEmpty()) {
                SapPaymentContractDetailVO detail = new SapPaymentContractDetailVO();
                detail.setCurrentCollectionAmount(paymentContract.getCurrentReceivedAmount());
                sapPaymentContractList.add(detail);
            }
            if (!CollectionUtils.isEmpty(sapPaymentContractList)) {
                contractCode = StrUtil.nullToDefault(sapPaymentContractList.stream().map(SapPaymentContractListVO::getContractCode).distinct().collect(Collectors.joining(",")),"");
                contractCode = S.equals(contractCode,"null") ? null : contractCode;
            }
            for (SapPaymentContractDetailVO sapPaymentContract : sapPaymentContractList) {
                PaymentCertItemListVO itemListVO = new PaymentCertItemListVO();
                itemListVO.setAccountCode("19");
                itemListVO.setCurrencyAmount(sapPaymentContract.getCurrentCollectionAmount());
                if (!entityList.isEmpty()) {
                    dis = !dis.contains(entityList.get(0).getDis()) ? dis + entityList.get(0).getDis() + "," : dis;
                    itemListVO.setLedgerFlag(S.equals(entityList.get(0).getDis(), "01") ? "0" : "A");
                } else {
                    throw new BusinessException("SAP客户无有效的销售组织目录");
                }
                // 为销售地区+销售员
                LabelValue salesAreaLabel = paymentContract.getSalesAreaLabel();
                String assignmentCode = StrUtil.nullToDefault(Optional.ofNullable(salesAreaLabel).orElse(new LabelValue()).getLabel(),"") + paymentContract.getSalerLabel();
                itemListVO.setAssignmentCode(assignmentCode);
                itemListVO.setBaseDate(paymentContract.getReceivedTime());
                itemListVO.setCustomerCode(paymentContract.getSapCustomerCode());
                // 项目文本 为客户名称
                String projectTxt = paymentContract.getSapCustomerName();
                itemListVO.setProjectText(projectTxt);
                itemListVO.setSalerId(paymentContract.getSaler());
                itemListVO.setPaymentNote(S.isNotEmpty(sapPaymentContract.getContractCode()) ? sapPaymentContract.getContractCode() : paymentContract.getSapCustomerName());
                itemListVO.setCustomerCode(paymentContract.getSapCustomerCode());
                itemListVO.setCustomerName(paymentContract.getSapCustomerName());
                paymentCertItems.add(itemListVO);
            }
            if (ObjectUtils.isNotEmpty(paymentContract.getCommission())) {
                PaymentCertItemListVO commissionListVO = new PaymentCertItemListVO();
                commissionListVO = BeanUtils.convert(commissionListVO, PaymentCertItemListVO.class);
                commissionListVO.setCurrencyAmount(paymentContract.getCommission())
                        .setProjectText("培训费");
            }
            // todo 手续费

        }
        Binder.bindRelations(paymentCertItems);
        paymentCertDetailVO.setPaymentCertItemList(paymentCertItems);
//        if (!contractCode.isEmpty()) {
//            contractCode = contractCode.substring(0, contractCode.length() - 1);
//        }
        if (!dis.isEmpty()) {
            dis = dis.substring(0, dis.length() - 1).replaceAll("01", "集团外客户").replaceAll("02", "集团内客户");
        }
        paymentCertDetailVO.setContractCode(contractCode);
        paymentCertDetailVO.setDis(dis);
        return paymentCertDetailVO;
    }

    @Override
    @Transactional
    public boolean batchGenPaymentCert(List<String> paymentRegisterIdList) throws JCoException {
        if (CollectionUtils.isEmpty(paymentRegisterIdList)) {
            throw new BusinessException("");
        }
        for (String paymentRegisterId : paymentRegisterIdList) {
            PaymentCertDetailVO paymentCertDetailVO = this.genPaymentCert(paymentRegisterId);
            this.createPaymentCert(paymentCertDetailVO);
        }
        return true;
    }

    @Override
    @Transactional
    public boolean createPaymentCert(PaymentCertDetailVO paymentCert) throws JCoException {
        // 构建sap接口参数
        Map<String, Object> param = new HashMap<>();
        param.put("BUKRS", iamTenantService.getEntity(IamSecurityUtils.getCurrentTenantId()).getOaNum()); // 公司代码
        param.put("GJAHR", paymentCert.getPostDate().format(DateTimeFormatter.ofPattern("yyyy"))); // 会计年度
        param.put("BLDAT", paymentCert.getPostDate().format(DateTimeFormatter.ofPattern("yyyyMMdd"))); // 凭证日期
        param.put("BUDAT", paymentCert.getPostDate().format(DateTimeFormatter.ofPattern("yyyyMMdd"))); // 过账日期
        param.put("MONAT", paymentCert.getPostDate().format(DateTimeFormatter.ofPattern("MM"))); // 会计期间
        param.put("BLART", "DZ"); // 凭证类型
        param.put("BKTXT", paymentCert.getCertTitle()); // 凭证抬头
        IamUser currentUser = IamSecurityUtils.getCurrentUser();
        param.put("USNAM", currentUser.getRealname()); // 用户名
        param.put("WAERS", "CNY"); // 货币码
        param.put("XBLNR", paymentCert.getContractCode()); // 客户采购订单编号
        List<PaymentCertItemListVO> paymentCertItemList = paymentCert.getPaymentCertItemList();
        List<Map<String, Object>> sapPaymentCertDetailVOList = paymentCertItemList.stream().map(item -> {
            Map<String, Object> map = new HashMap<>();
            map.put("BSCHL", item.getAccountCode()); //记账代码
            map.put("HKONT", item.getAccountTitle()); // 总账科目
            map.put("KOSTL", item.getCostCenter()); // 成本中心
            map.put("WRBTR", item.getCurrencyAmount()); // 金额
            map.put("UMSKZ", item.getLedgerFlag()); // 特殊总账标识
            map.put("ZUONR", item.getAssignmentCode()); // 分配编号
            item.setBaseDate(item.getBaseDate() == null ? LocalDateTime.now() : item.getBaseDate());
            map.put("ZFBDT", item.getBaseDate().format(DateTimeFormatter.ofPattern("yyyyMMdd"))); // 过账日期
            map.put("KUNNR", item.getCustomerCode()); // 客户代码
            map.put("SGTXT", item.getProjectText()); // 客户名称
            map.put("RSTGR", item.getReasonCode()); // 付款原因代码
            map.put("ZTEXT1", item.getSalerName()); // 员工姓名
            map.put("ZTEXT2", item.getSalerNum()); // 员工编号
            map.put("KIDNO", item.getPaymentNote()); // 付款参考
            return map;
        }).toList();
        // 调用SAP接口获取凭证号
        Map<String, String> res = sapUtil.paymentCert("ZRFC_CRM_ACCOUNTING", param, sapPaymentCertDetailVOList);
        if (S.equals(res.get("code"), "S")) {
            paymentCert.setSapCertCode(res.get("sapCertCode"));
            paymentCert.setSapPushStatus(2); // 成功
        } else {
            paymentCert.setSapResponseMsg(res.get("msg"));
            paymentCert.setSapPushStatus(1); // 失败
        }
        LambdaQueryWrapper<PaymentCert> paymentCertQuery = new LambdaQueryWrapper<>();
        paymentCertQuery.eq(PaymentCert::getPaymentRegisterId, paymentCert.getPaymentRegisterId());
        this.deleteEntities(paymentCertQuery);
        paymentCert.setId(null);
        this.createEntity(paymentCert);
        PaymentRegisterListVO paymentRegister = paymentCert.getPaymentRegister();
        paymentRegister.setId(paymentCert.getPaymentRegisterId());
        if (2 == paymentCert.getSapPushStatus()) {
            paymentRegister.setCerted("1");
        } else {
            paymentRegister.setCerted("0");
        }
        paymentRegisterService.updateEntity(paymentRegister);
        paymentCertItemList.forEach(item -> item.setPaymentCertId(paymentCert.getId()));
        paymentCertItemService.createOrUpdateEntities(paymentCertItemList);
        return true;
    }
}